using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;

namespace CloudStorage.API.Blobs
{
	/// <summary>
	/// A Data Context for accessing and manipulating Cloud Storage Blobs
	/// </summary>
	public interface IBlobDataContext
	{
		/// <summary>
		/// Updates an existing blobInfo or creates a new blobInfo.
		/// </summary>
		/// <returns>True if the blobInfo was updated or created. False if the blobInfo has changed since the last time</returns>
		/// <param name="blobInfo">Blob data</param>		
    /// <param name="contents">The blob content</param>
    void PutBlob(IBlobInfo blobInfo, Stream contents);

		/// <summary>
		/// Get the blob contents and properties if the blob exists. Null otherwise.
		/// </summary>
		/// <param name="blobName">The name of the blob</param>
		/// This object should contain a writable stream or should be a default constructed object.
		/// <returns>The properties of the blob if the blob exists.</returns>
		IBlobInfo GetBlob(string blobName);

		/// <summary>
		/// Get part of the blob contents and properties if the blob exists
		/// </summary>
		/// <param name="blobName">The name of the blob</param>
		/// <param name="fromByte">Lower range of the blob part to get</param>
		/// <param name="toByte">Upper range of the blob part to get</param>
		/// <returns>A blob data result with a part of a blob as content</returns>
		IBlobInfo GetBlob(string blobName, long fromByte, long toByte);

		/// <summary>
		/// Get the properties of the blob if it exists.
		/// This method is also the simplest way to check if a blob exists.
		/// </summary>
		/// <param name="blobName">The name of the blob</param>
		/// <returns>The properties of the blob if it exists. Null otherwise.
		/// The properties for the contents of the blob are not set.</returns>
		IBlobInfo GetBlobProperties(string blobName);

		/// <summary>
		/// This operation creates a new block to be committed as part of a blob.
		/// </summary>
		/// <param name="blobName">The name of the blob</param>
		/// <param name="blockId">The Id of this block</param>
		/// <param name="stream">The block data, max 4 mb</param>
		void PutBlock(string blobName, string blockId, Stream stream);

		/// <summary>
		/// This operation writes a blob by specifying the list of block IDs that make up the blob.
		/// </summary>
		/// <param name="blobName">The name of the blob</param>
		/// <param name="blockIds">The Ids of the blocks</param>
		void PutBlockList(string blobName, IEnumerable<string> blockIds);

		/// <summary>
		/// This operation retrieves the list of blocks that have been uploaded as part of a blob. 
		/// </summary>
		/// <param name="blobName">The name of the blob</param>    
		/// <returns>The block list</returns>
		IEnumerable<KeyValuePair<string, long>> GetBlockList(string blobName);

		/// <summary>
		/// This operation copies a blob to a destination within the storage account.
		/// </summary>
		/// <param name="blobName">The name of the new Blob</param>
		/// <param name="fromAccountName">The blob storage account to copy from</param>
		/// <param name="fromContainerName">The blob container to copy from</param>
		/// <param name="fromBlobName">The blob copy</param>
		void CopyBlob(string blobName, string fromAccountName, string fromContainerName, string fromBlobName);

		/// <summary>
		/// Get the metadata of the blob if it exists.
		/// Refreshes the metadata from the cloud storage.
		/// </summary>		
		/// <param name="blobName">The blob name</param>
		/// <returns>The metadata of the blob. Null otherwise.</returns>
		NameValueCollection GetBlobMetadata(string blobName);

		/// <summary>
		/// Set the metadata of the blob if it exists.
		/// </summary>		
		/// <param name="blobName">The blob name</param>
		/// <param name="metadata">The metadata</param>
		/// <returns>True if the meta data was set</returns>
		void SetBlobMetadata(string blobName, NameValueCollection metadata);

		/// <summary>
		/// Delete a blob with the given name
		/// </summary>		
		/// <param name="blobName">The blob name</param>
		/// <returns>true if the blob exists and was successfully deleted, false if the blob does not exist</returns>
		void DeleteBlob(string blobName);		
	}
}